﻿using DG.Tweening;
using System;
using UnityEngine;
using UnityEngine.UI;

namespace CGF
{
    public static class DOVirtualCGF
    {
        public class BezierTask
        {
            Vector2 startPos, ctrlPos, endPos;
            float duration;
            Action<Vector2> onUpdate;
            Action onComplete;
            float time;
            public BezierTask(Vector2 startPos, Vector2 ctrlPos, Vector2 endPos, float duration, Action<Vector2> onUpdate)
            {
                this.startPos = startPos;
                this.ctrlPos = ctrlPos;
                this.endPos = endPos;
                this.duration = duration;
                this.onUpdate = onUpdate;
                CGFramework.Instance.updateAction += Update;
            }
            private void Update()
            {
                if (time < duration)
                {
                    time += Time.deltaTime;
                    if (time > duration)
                    {
                        time = duration;
                    }
                    float timeNormalized = time / duration;
                    Vector2 pos = MathHelper.GetBezierPoint(startPos, ctrlPos, endPos, timeNormalized);
                    onUpdate?.Invoke(pos);
                    if (time == duration)
                    {
                        CGFramework.Instance.updateAction -= Update;
                        onComplete?.Invoke();
                    }
                }
            }

            public void OnComplete(Action onComplete)
            {
                this.onComplete = onComplete;
            }
        }

        //贝塞尔曲线移动
        public static BezierTask Bezier(Vector2 startPos, Vector2 ctrlPos, Vector2 endPos, float duration, Action<Vector2> onUpdate)
        {
            return new BezierTask(startPos, ctrlPos, endPos, duration, onUpdate);
        }

        //延迟调用
        public static void DelayedCall(float dalay, TweenCallback action, bool ignorTimeScale = true)
        {
            DOVirtual.DelayedCall(dalay, action, ignorTimeScale);
        }
    }

    /// <summary>
    /// DOTween扩展类
    /// </summary>
    public static class DOTweenExtend
    {
        public static Tweener DOAlpha(this Transform target, float endAlpha, bool includeChildren)
        {
            return target.DOAlpha(endAlpha, 0, includeChildren);
        }

        public static Tweener DOAlpha(this Transform target, float endAlpha, float duration = 0, bool includeChildren = true)
        {
            if (includeChildren)
            {
                CanvasGroup group = target.GetComponent<CanvasGroup>();
                if (!group) group = target.gameObject.AddComponent<CanvasGroup>();
                if (duration == 0)
                {
                    group.alpha = endAlpha;
                    return null;
                }
                else
                {
                    return group.DOFade(endAlpha, duration);
                }
            }
            else
            {
                if (duration == 0)
                {
                    Graphic graphic = target.GetComponent<Graphic>();
                    Color color = graphic.color;
                    color.a = endAlpha;
                    graphic.color = color;
                    return null;
                }
                else
                {
                    return target.GetComponent<Graphic>().DOFade(endAlpha, duration);
                }
            }
        }

        public static void DOKillAlpha(this Transform target)
        {
            CanvasGroup group = target.GetComponent<CanvasGroup>();
            if (group)
            {
                group.DOKill();
            }
        }

        public static void DOShake(this RectTransform target, Vector2 originPos, Vector2 offset, float duration = 0.5f, int times = 5)
        {
            Vector2 posA = originPos + offset;
            Vector2 posB = originPos - offset;
            float subDuration = duration / (float)times;
            Sequence quence = DOTween.Sequence();
            for (int i = 0; i < times; i++)
            {
                quence.Append(target.DOAnchorPos(posA, subDuration));
                quence.Append(target.DOAnchorPos(posB, subDuration));
                offset *= 0.5f;
                posA = originPos + offset;
                posB = originPos - offset;
            }
            quence.Play();
        }

    }
}